<template>
  <basic-drawer
    :visible="visible"
    :title="title"
    ok-text="保存配置"
    @ok="handleSubmit"
    @open="handleBeforeOpen"
    @close="handleBeforeClose"
    @cancel="emits('update:visible', false)">
    <a-form
      ref="formRef"
      :model="formData"
      :rules="formRules"
      layout="vertical">
      <a-form-item
        field="name"
        label="规则名称"
        hide-asterisk
        asterisk-position="end"
        required>
        <a-input
          v-model="formData.name"
          :max-length="20"
          class="!w-100"
          placeholder="请输入规则名称">
        </a-input>
      </a-form-item>
      <a-form-item
        label="匹配规则"
        hide-asterisk
        asterisk-position="end"
        required>
        <matching-rule-view
          ref="matchingView"
          v-model="ruleGroups"
          class="w-full"></matching-rule-view>
      </a-form-item>
      <a-form-item
        field="pathRadio"
        label="路径"
        hide-asterisk
        asterisk-position="end"
        :required="formData.pathRadio === 1 ? false : true">
        <div>
          <a-radio-group
            v-model="formData.pathRadio"
            @change="handlePathChange">
            <a-radio :value="1">
              <span class="radio-label">保留</span>
              <span class="radio-desc">（原始请求中的路径）</span>
            </a-radio>
            <a-radio :value="2">
              <span class="radio-label">重写到</span>
              <span class="radio-desc">
                （例如：content/images/thumbnails）
              </span>
            </a-radio>
          </a-radio-group>
          <a-form-item
            v-if="formData.pathRadio === 2"
            hide-label
            field="config.path"
            :required="formData.pathRadio !== 2">
            <a-input
              v-model="formData.config.path"
              class="path-input !w-100 mt-2"
              placeholder="请配置路径">
              <template #prepend>/</template>
            </a-input>
          </a-form-item>
        </div>
      </a-form-item>
      <a-form-item
        label="查询"
        field="queryRadio"
        hide-asterisk
        :required="formData.queryRadio === 1 ? false : true">
        <div>
          <a-radio-group
            v-model="formData.queryRadio"
            @change="handleQueryChange">
            <a-radio :value="1">
              <span class="radio-label">保留</span>
              <span class="radio-desc">（原始请求中的查询）</span>
            </a-radio>
            <a-radio :value="2">
              <span class="radio-label">重写到</span>
              <span class="radio-desc">（例如：page=1234）</span>
            </a-radio>
          </a-radio-group>
          <a-form-item
            v-if="formData.queryRadio === 2"
            hide-label
            field="config.query_string"
            :required="formData.queryRadio !== 2">
            <a-input
              v-model="formData.config.query_string"
              class="path-input !w-100 mt-2"
              placeholder="请配置路径">
              <template #prepend>?</template>
            </a-input>
          </a-form-item>
          <div v-if="errorFlag" class="error-msg text-#f76560 text-xs/5">
            重写规则不能同时保留路径和查询。请重写此路径或查询。
          </div>
        </div>
      </a-form-item>
      <a-form-item
        v-if="list.length > 0"
        field="order"
        label="执行优先级"
        hide-asterisk
        asterisk-position="end"
        required>
        <section class="flex flex-col">
          <a-select
            v-model="formData.order"
            placeholder="请选择执行优先级"
            class="!w-100"
            :options="getOption"
            @change="handleChange" />
          <a-form-item
            v-if="formData.order === A_EXECUTION_PRIORITY.CUSTOM"
            field="priority"
            hide-label
            asterisk-position="end"
            class="!mb-0 mt-2"
            required>
            <a-select
              v-model="formData.priority"
              class="w-[336px]"
              placeholder="优先触发创建的规则，再触发选择的规则">
              <a-option
                v-for="item in props?.record?.id ? filterList : list"
                :key="item.id"
                :label="item.name"
                :value="item.priority" />
            </a-select>
          </a-form-item>
          <span
            v-if="formData.order === A_EXECUTION_PRIORITY.CUSTOM"
            class="text-5 text-xs/5"
            >在此规则前执行。</span
          >
        </section>
      </a-form-item>
    </a-form>
  </basic-drawer>
</template>
<script lang="ts" setup>
import type { UrlListItem } from '@/apis/model/transform'
import {
  addApiSiteConversionRuleApi,
  getApiSiteConversionRuleApi,
  getApiSiteConversionRuleQueryApi,
  updateApiSiteConversionRuleApi
} from '@/apis/modules/site/transform'
import type { CloudFilterBarState } from '@/components/filter-bar/types'
import type { IMatchingGroup } from '@/components/MatchingRule/types'
import { getFieldValue } from '@/components/MatchingRule/utils'
import { type FieldRule, type FormInstance } from '@arco-design/web-vue'
import { omit } from 'lodash-es'
import { v4 as uuidV4 } from 'uuid'
interface IProps {
  visible: boolean
  record?: any
  type: number
  id: string
}
const props = withDefaults(defineProps<IProps>(), {
  visible: false,
  type: 1
})
interface IEmits {
  (e: 'update:visible', value: boolean): void
  (e: 'refresh'): void
}
const emits = defineEmits<IEmits>()
const title = computed(() => (props?.record?.id ? '编辑规则' : '创建规则'))
const formRef = ref<FormInstance>()
const matchingView = ref()
const formData = ref({
  name: '',
  order: undefined,
  priority: undefined,
  config: { path: '', query_string: '' },
  pathRadio: 2,
  queryRadio: 2,
  type: props.type
})
const formRules = computed<{ [key: string]: FieldRule[] }>(() => {
  return {
    name: [
      {
        required: true,
        message: '请输入规则名称'
      }
      // { validator: validateTitle }
    ],
    'config.path': [
      {
        required: true,
        validator: (value: string, callback: any) => {
          if (!value) {
            return callback('请配置路径')
          } else if (value.charAt(0) === '/') {
            callback('路径格式错误，不能以/开头')
          } else {
            callback()
          }
        },
        trigger: 'blur'
      }
    ],
    'config.query_string': [
      {
        required: true,
        validator: (value: string, callback: any) => {
          if (!value) {
            callback('请配置路径')
          } else if (value.charAt(0) === '?') {
            callback('查询格式错误，不能以?开头')
          } else {
            callback()
          }
        },
        trigger: 'blur'
      }
    ],
    order: [
      {
        required: true,
        message: '请选择执行优先级'
      }
    ],
    priority: [
      {
        required: true,
        message: '请选择自定义规则'
      }
    ]
  }
})
const ruleGroups = ref<IMatchingGroup[]>([
  {
    uuid: uuidV4(),
    rules: [
      {
        uuid: uuidV4(),
        field: '',
        operator: '',
        value: '',
        custom_field: ''
      }
    ]
  }
])

const errorFlag = ref(false)
const isPathAndQueryRetain = computed(() => {
  return formData.value.pathRadio === 1 && formData.value.queryRadio === 1
})
watch(
  isPathAndQueryRetain,
  (val) => {
    if (!val) return (errorFlag.value = false)
    errorFlag.value = true
  },
  { immediate: true }
)
//路径改变清空值
const handlePathChange = (val) => {
  if (val === 1) formData.value.path = ''
}
//查询改变清空值
const handleQueryChange = (val) => {
  if (val === 1) formData.value.query = ''
}
const params = ref<CloudFilterBarState>({
  order: 'asc',
  sort: 'priority',
  type: props.type,
  site_id: props.id
})
const list = ref<UrlListItem[]>([])
const filterList = ref<UrlListItem[]>([])
const { run, pagination } = useListRequest(getApiSiteConversionRuleQueryApi, {
  params,
  immediate: false,
  async afterFn(res) {
    await nextTick()
    list.value = res.list || []
    if (!list.value.length) return
    filterList.value = res.list.filter((item) => item.id !== props?.record?.id)
  }
})
pagination.value.pageSize = 1000
const prePriority = ref(0)
const handleChange = (val) => {
  if (val === 2) {
    if (prePriority.value === list.value[0].priority) {
      formData.value.priority = prePriority.value + 1
    } else if (
      prePriority.value === list.value[list.value.length - 1].priority
    ) {
      formData.value.priority = prePriority.value - 1
    }
  }
}
const getOption = computed(() => {
  if (props.record?.id) {
    return list.value.length > 2 ? priorityOptions : priorityOptions.slice(0, 2)
  } else {
    return list.value.length > 1 ? priorityOptions : priorityOptions.slice(0, 2)
  }
})
const { request } = useRequest(getApiSiteConversionRuleApi, {
  success(res) {
    Object.assign(formData.value, res)
    prePriority.value = res.priority!
    ruleGroups.value[0].rules = res.conditions.map((item) => {
      return {
        uuid: uuidV4(),
        ...item,
        value:
          getFieldValue(item)!.count > 1 ? item.value : item.value.toString()
      }
    })
    formData.value.pathRadio = res.config.path
      ? (formData.value.pathRadio = 2)
      : 1
    formData.value.queryRadio = res.config.query_string
      ? (formData.value.queryRadio = 2)
      : 1

    if (list.value.length) {
      if (list.value.length === 1)
        return (formData.value.order = formData.value.priority)
      const priorityArr = list.value.map((item: UrlListItem) => item.priority!)
      const min = Math.min(...priorityArr)
      const max = Math.max(...priorityArr)
      switch (+formData.value.priority!) {
        case min:
          formData.value.order = A_EXECUTION_PRIORITY.FIRST
          break
        case max:
          formData.value.order = A_EXECUTION_PRIORITY.LAST
          break
        default:
          formData.value.order = A_EXECUTION_PRIORITY.CUSTOM
      }
    } else {
      formData.value.order = formData.value.priority
    }
    if (formData.value.order === A_EXECUTION_PRIORITY.CUSTOM) {
      formData.value.priority = formData.value.priority + 1
    } else {
      formData.value.priority = formData.value.priority!
    }
  }
})

const handleBeforeOpen = async () => {
  await run()
  if (props.record) request({ id: props.record?.id })
}
const handleBeforeClose = async () => {
  await formRef.value?.resetFields()
  matchingView.value?.reset()
  emits('update:visible', false)
}
async function handleSubmit() {
  const error = await formRef.value?.validate()
  const error1 = await matchingView.value.validate()
  if (error || !error1) return false
  if (isPathAndQueryRetain.value) {
    return ToastUtils.error(
      '重写规则不能同时保留路径和查询。请重写此路径或查询。'
    )
  }
  const data: any = {
    ...omit(formData.value, 'pathRadio', 'queryRadio', 'order'),
    conditions: ruleGroups.value[0].rules.map((item) => {
      return {
        ...item,
        value: !Array.isArray(item.value)
          ? item.value
            ? [item.value]
            : []
          : item.value.filter(Boolean)
      }
    }),
    config: {
      path: formData.value?.pathRadio === 1 ? '' : formData.value?.config.path,
      query_string:
        formData.value?.queryRadio === 1
          ? ''
          : formData.value?.config.query_string
    },
    id: props.record ? props.record?.id : undefined,
    site_id: props.record ? undefined : props.id
  }
  if (formData.value?.order === A_EXECUTION_PRIORITY.FIRST) {
    data.priority = 1
  } else if (formData.value?.order === A_EXECUTION_PRIORITY.LAST) {
    data.priority = 0
  } else {
    data.priority = formData?.value?.priority
  }
  const api_path = props.record
    ? updateApiSiteConversionRuleApi
    : addApiSiteConversionRuleApi
  api_path(data).then(() => {
    ToastUtils.success('操作成功')
    emits('update:visible', false)
    emits('refresh')
  })
}
</script>

<style lang="less" scoped>
.path-input {
  :deep(.arco-input-wrapper) {
    border-top-left-radius: 0 !important;
    border-bottom-left-radius: 0 !important;
  }
  :deep(.arco-input-prepend) {
    border-top-left-radius: 4px;
    border-bottom-left-radius: 4px;
  }
}
</style>
